﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Collections;

namespace Ellanet
{
    class vmrunGUIXmlWrapper
    {
        private const string encryptionKey = "Ch4rlt0n";

        private XmlDocument vmrunGUIXmlDoc;
        private string _xmlPath = null;

        public enum GuestStatus
        {
            PoweredOn,
            PoweredOff,
            Unknown
        }

        public struct VMwareGuest
        {
            public string vmxPath;
            public string host;
            public GuestStatus status;
        }

        public vmrunGUIXmlWrapper(string xmlPath)
        {
            _xmlPath = xmlPath;
            vmrunGUIXmlDoc = new XmlDocument();

            if (File.Exists(_xmlPath))
            {
                vmrunGUIXmlDoc.Load(_xmlPath);
            }
            else
            {
                vmrunGUIXmlDoc.LoadXml("<vmrun_gui><vmrun><path /></vmrun><hosts /><guests /><credentials_cache /></vmrun_gui>");
                SaveXml();
            }
        }

        public void SaveXml()
        {
            vmrunGUIXmlDoc.Save(_xmlPath);
        }

        public string GetvmrunPath()
        {
            return vmrunGUIXmlDoc.SelectSingleNode("vmrun_gui/vmrun/path").InnerText;
        }

        public void SetvmrunPath(string vmrunPath)
        {
            vmrunGUIXmlDoc.SelectSingleNode("vmrun_gui/vmrun/path").InnerText = vmrunPath;
        }

        public void AddHost(string name, string type, string host, string port, string arguments, string localhost, string overrideArguments, string credentials)
        {
            XmlNode hostNode = vmrunGUIXmlDoc.CreateElement("host");
            hostNode.InnerXml = "<name /><type /><host /><port /><arguments /><localhost /><override /><credentials />";
            hostNode.SelectSingleNode("name").InnerText = name;
            hostNode.SelectSingleNode("type").InnerText = type;
            hostNode.SelectSingleNode("host").InnerText = host;
            hostNode.SelectSingleNode("port").InnerText = port;
            hostNode.SelectSingleNode("arguments").InnerText = arguments;
            hostNode.SelectSingleNode("localhost").InnerText = localhost;
            hostNode.SelectSingleNode("override").InnerText = overrideArguments;
            hostNode.SelectSingleNode("credentials").InnerText = credentials;
            vmrunGUIXmlDoc.SelectSingleNode("vmrun_gui/hosts").AppendChild(hostNode);
        }

        public bool HostExists(string hostName)
        {
            return Convert.ToBoolean(vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]", hostName)).Count > 0);
        }

        public ArrayList GetHostNames()
        {
            ArrayList hosts = new ArrayList();

            foreach (XmlNode hostNode in vmrunGUIXmlDoc.SelectNodes("vmrun_gui/hosts/host"))
            {
                hosts.Add(hostNode.SelectSingleNode("name").InnerText);
            }

            hosts.Sort();
            return hosts;
        }

        public string GetHostType(string hostName)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]", hostName)).Count > 0)
            {
                return vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]/type", hostName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public void RemoveHost(string hostName)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]", hostName)).Count > 0)
            {
                XmlNode hostNode = vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]", hostName));
                hostNode.ParentNode.RemoveChild(hostNode);
            }
        }

        public string GetHostChildNodeInnerText(string hostName, string nodeName)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[name=\"{0}\" and {1}]", hostName, nodeName)).Count > 0)
            {
                return vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/hosts/host[name=\"{0}\"]/{1}", hostName, nodeName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public ArrayList GetHostsByCredentials(string credentials)
        {
            ArrayList hosts = new ArrayList();

            foreach (XmlNode hostNode in vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[credentials=\"{0}\"]", credentials)))
            {
                hosts.Add(hostNode.SelectSingleNode("name").InnerText);
            }

            hosts.Sort();
            return hosts;
        }

        public void AddGuest(string name, string host, string vmxPath, string description, string credentials)
        {
            XmlNode guestNode = vmrunGUIXmlDoc.CreateElement("guest");
            guestNode.InnerXml = "<name /><host /><vmx_path /><description /><credentials />";
            guestNode.SelectSingleNode("name").InnerText = name;
            guestNode.SelectSingleNode("host").InnerText = host;
            guestNode.SelectSingleNode("vmx_path").InnerText = vmxPath;
            guestNode.SelectSingleNode("description").InnerText = description;
            guestNode.SelectSingleNode("credentials").InnerText = credentials;
            vmrunGUIXmlDoc.SelectSingleNode("vmrun_gui/guests").AppendChild(guestNode);
        }

        public ArrayList GetGuestsFromHost(string hostName)
        {
            ArrayList guests = new ArrayList();

            foreach (XmlNode guestNode in vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[host=\"{0}\"]", hostName)))
            {
                guests.Add(guestNode.SelectSingleNode("vmx_path").InnerText);
            }

            guests.Sort();
            return guests;
        }

        public string GetGuestChildNodeInnerText(string vmxPath, string hostName, string nodeName)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\" and {2}]", vmxPath, hostName, nodeName)).Count > 0)
            {
                return vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\"]/{2}", vmxPath, hostName, nodeName)).InnerText;
            }
            else
            {
                return null;
            }
        }

        public void SetGuestChildNodeInnerText(string vmxPath, string hostName, string nodeName, string value)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\" and {2}]", vmxPath, hostName, nodeName)).Count > 0)
            {
                vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\"]/{2}", vmxPath, hostName, nodeName)).InnerText = value;
            }
        }

        public void RemoveGuest(string vmxPath, string hostName)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\"]", vmxPath, hostName)).Count > 0)
            {
                XmlNode guestNode = vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\"]", vmxPath, hostName));
                guestNode.ParentNode.RemoveChild(guestNode);
            }
        }

        public bool GuestExists(string vmxPath, string hostName)
        {
            return Convert.ToBoolean(vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[vmx_path=\"{0}\" and host=\"{1}\"]", vmxPath, hostName)).Count > 0);
        }

        public VMwareGuest[] GetGuestsByCredentials(string credentials)
        {
            ArrayList guests = new ArrayList();

            foreach (XmlNode guestNode in vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[credentials=\"{0}\"]", credentials)))
            {
                VMwareGuest guest = new VMwareGuest();
                guest.host = guestNode.SelectSingleNode("host").InnerText;
                guest.vmxPath = guestNode.SelectSingleNode("vmx_path").InnerText;
                guests.Add(guest);
            }

            return (VMwareGuest[])guests.ToArray(typeof(VMwareGuest));
        }

        public void GetCredentials(string name, out string username, out string password)
        {
            username = null;
            password = null;

            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/credentials_cache/credentials[name=\"{0}\"]", name)).Count > 0)
            {
                XmlNode crdentialsNode = vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/credentials_cache/credentials[name=\"{0}\"]", name));
                username = crdentialsNode.SelectSingleNode("username").InnerText;
                password = new StringEncryption().Decrypt(crdentialsNode.SelectSingleNode("password").InnerText, encryptionKey);
            }
        }

        public ArrayList GetCredentialsNames()
        {
            ArrayList credentials = new ArrayList();

            foreach (XmlNode hostNode in vmrunGUIXmlDoc.SelectNodes("vmrun_gui/credentials_cache/credentials"))
            {
                credentials.Add(hostNode.SelectSingleNode("name").InnerText);
            }

            credentials.Sort();
            return credentials;
        }

        public void AddCredentials(string name, string username, string password)
        {
            XmlNode hostNode = vmrunGUIXmlDoc.CreateElement("credentials");
            hostNode.InnerXml = "<name /><username /><password />";
            hostNode.SelectSingleNode("name").InnerText = name;
            hostNode.SelectSingleNode("username").InnerText = username;
            hostNode.SelectSingleNode("password").InnerText = new StringEncryption().Encrypt(password, encryptionKey);
            vmrunGUIXmlDoc.SelectSingleNode("vmrun_gui/credentials_cache").AppendChild(hostNode);
        }

        public void RemoveCredentials(string name)
        {
            if (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/credentials_cache/credentials[name=\"{0}\"]", name)).Count > 0)
            {
                XmlNode crdentialsNode = vmrunGUIXmlDoc.SelectSingleNode(String.Format("vmrun_gui/credentials_cache/credentials[name=\"{0}\"]", name));
                crdentialsNode.ParentNode.RemoveChild(crdentialsNode);
            }
        }

        public bool CredentialsExists(string name)
        {
            return Convert.ToBoolean(vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/credentials_cache/credentials[name=\"{0}\"]", name)).Count > 0);
        }

        public void UpdateCredentialsOnHostsAndGuests(string previousName, string newName)
        {
            foreach (XmlNode guestNode in vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[credentials=\"{0}\"]", previousName)))
            {
                guestNode.SelectSingleNode("credentials").InnerText = newName;
            }

            foreach (XmlNode hostNode in vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[credentials=\"{0}\"]", previousName)))
            {
                hostNode.SelectSingleNode("credentials").InnerText = newName;
            }
        }

        public bool CredentialsInUse(string name)
        {
            if ((vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/guests/guest[credentials=\"{0}\"]", name)).Count > 0) || (vmrunGUIXmlDoc.SelectNodes(String.Format("vmrun_gui/hosts/host[credentials=\"{0}\"]", name)).Count > 0))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
